/**
 * Deep4jNetworkWrapper.java created by zhangzhidong 
 * at 上午10:07:50 2017年5月26日
 */
package cn.edu.bjtu.model.core;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

import org.deeplearning4j.eval.Evaluation;
import org.nd4j.linalg.api.ndarray.INDArray;
import org.nd4j.linalg.dataset.api.iterator.DataSetIterator;
import org.textplantform.common.core.Deep4jModelType;
import org.textplantform.common.core.LoggerSupport;
import org.textplantform.common.provider.NetworkModelService;

import cn.edu.bjtu.core.NeuronNetwork;

/**
 * 包装类,支持更新时间获取
 * @author Alex
 * 
 */
public class Deep4jNetworkWrapper extends LoggerSupport implements NeuronNetwork{
	//dubbo remote service
	private NetworkModelService nms;
	private int intCpuNumber = -1;
	private ThreadFactory _tf = new ThreadFactory() {
		AtomicInteger ai = new AtomicInteger(0);
		public Thread newThread(Runnable r) {
			Thread t = new Thread(r);
			t.setDaemon(true);
			t.setName("classify-worker-"+ai.getAndIncrement());
			return t;
		}
	};
	
	private ExecutorService es = Executors.newFixedThreadPool(intCpuNumber,_tf);
	private Slave slave = null;
	
	/**
	 * @param nms 读取神经网络模型所用的类
	 * @param cpuNum 支持多少个线程并发的去运算,如果-1,则为availableProcessors();
	 */
	public Deep4jNetworkWrapper(NetworkModelService nms,int cpuNum) {
		this.nms = nms;
		intCpuNumber = (cpuNum ==-1 ? Runtime.getRuntime().availableProcessors():cpuNum);
	}
	@Override
	public INDArray[] output(INDArray... input) throws Exception{
		Future<INDArray[]> f = es.submit(()->slave.output(input));
		return f.get();
	}	
	@Override
	public Future<INDArray[]> outputAsync(INDArray... input) throws Exception {
		return es.submit(()->slave.output(input));
	}
	 @Override
	public Evaluation evaluate(DataSetIterator iterator) throws Exception {
		Future<Evaluation> f = es.submit(()-> slave.evaluate(iterator));
		return f.get();
	}
	 
	@Override
	public Future<Evaluation> evaluateAsync(DataSetIterator iterator) throws Exception {
		return es.submit(()-> slave.evaluate(iterator));
	}


	@Override
	public void load() throws Exception {
		switch(nms.getType()){
			case ComputationGraph:
				slave = new ComputationGraphSlave(nms);
				break;
			case MultiLayerNetwork:
				slave  = new MultiLayerNetworkSlave(nms);
				break;
			default:
				throw new IllegalArgumentException("unknow type");
		}
		slave.load();
	}

	@Override
	public Deep4jModelType getActualType() {
		return slave.getActualType();
	}
	public Object get(){
		return slave.get();
	}
	

}
